package com.gome.ocean.service.mail;

import java.io.File;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.activation.FileDataSource;
import javax.mail.BodyPart;
import javax.mail.Message.RecipientType;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import javax.mail.internet.MimeUtility;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.support.PropertiesLoaderUtils;
import org.springframework.stereotype.Component;
import org.springframework.util.ClassUtils;

import com.gome.ocean.service.velocity.VelocityBean;

/**
 * 发送邮件
 * 
 * @author haqiaolong 2016年4月5日 下午3:16:17
 * @since 5.0.0
 */
@Component("simpleMailSender")
public class SimpleMailSender implements InitializingBean, DisposableBean {

    private static final Logger logger = LoggerFactory.getLogger(SimpleMailSender.class);

    @Autowired
    private VelocityBean                velocityBean;
    /**
     * 发送邮件的props文件
     */
    private transient Properties        props;
    /**
     * 邮件服务器登录验证
     */
    private transient MailAuthenticator authenticator;

    /**
     * 邮箱session
     */
    private transient Session session;

    private static String mailAlertContext;

    private static String mailDefaultUser;

    @Override
    public void afterPropertiesSet() throws Exception {
        props = PropertiesLoaderUtils.loadAllProperties(EmailConstants.DEFAULT_MAIL_FILE,
            ClassUtils.getDefaultClassLoader());
        props.put("mail.smtp.host", props.getProperty(EmailConstants.MAIL_SMTP_HOST));
        // 初始化props
        boolean isAuth = Boolean.parseBoolean(props.getProperty(EmailConstants.MAIL_SMTP_AUTH));
        if (isAuth) {
            // 验证
            String username = props.getProperty(EmailConstants.SEND_MAIL_USERNAME);
            String password = props.getProperty(EmailConstants.SEND_MAIL_PASSWORD);
            authenticator = new MailAuthenticator(username, password);
        }
        // 创建session
        session = Session.getInstance(props, authenticator);
        mailAlertContext = props.getProperty(EmailConstants.MAIL_ALERT_CONTEXT);
        mailDefaultUser = props.getProperty(EmailConstants.MAIL_DEFAULT_USER);
        if (logger.isDebugEnabled()) {
            logger.debug("mail init success!");
        }
    }

    @Override
    public void destroy() throws Exception {

    }

    /**
     * 发送邮件
     * 
     * @param recipient 收件人邮箱地址
     * @param subject 邮件主题
     * @param content 邮件内容
     * @throws AddressException
     * @throws MessagingException
     */
    public void send(String recipient, EmailSubject subject, Map<String, String> contextMaps) throws AddressException,
                                                                                              MessagingException {
        // 创建mime类型邮件
        final MimeMessage message = new MimeMessage(session);
        // 设置发信人
        // message.setFrom(new InternetAddress(authenticator.getUsername()));
        // 设置收件人
        message.setRecipient(RecipientType.TO, new InternetAddress(recipient));
        // 设置主题
        message.setSubject(subject.getSubject());
        // 设置邮件内容
        message.setContent(getEmailContext(contextMaps), "text/html;charset=utf-8");
        // 发送
        Transport.send(message);
    }

    /**
     * 发送邮件
     * 
     * @param recipient 收件人邮箱地址
     * @param subject 邮件主题
     * @param content 邮件内容
     * @throws AddressException
     * @throws MessagingException
     */
    public void send(List<String> recipients, EmailSubject subject, String content) throws AddressException,
                                                                                    MessagingException {
        // 创建mime类型邮件
        final MimeMessage message = new MimeMessage(session);
        // 设置发信人
        message.setFrom(new InternetAddress(authenticator.getUsername()));
        // 设置收件人们
        final int num = recipients.size();
        InternetAddress[] addresses = new InternetAddress[num];
        for (int i = 0; i < num; i++) {
            addresses[i] = new InternetAddress(recipients.get(i));
        }
        message.setRecipients(RecipientType.TO, addresses);
        // 设置主题
        message.setSubject(subject.getSubject());
        // 设置邮件内容
        message.setContent(content, "text/html;charset=utf-8");
        // 发送
        Transport.send(message);
    }

    /**
     * 群发邮件
     * 
     * @param recipients 收件人们
     * @param subject 主题
     * @param content 内容
     * @throws AddressException
     * @throws MessagingException
     */
    public void send(List<String> recipients, EmailSubject subject,
                     Map<String, String> contextMaps) throws AddressException, MessagingException {
        // 创建mime类型邮件
        final MimeMessage message = new MimeMessage(session);
        // 设置发信人
        message.setFrom(new InternetAddress(authenticator.getUsername()));
        // 设置收件人们
        final int num = recipients.size();
        InternetAddress[] addresses = new InternetAddress[num];
        for (int i = 0; i < num; i++) {
            addresses[i] = new InternetAddress(recipients.get(i));
        }
        message.setRecipients(RecipientType.TO, addresses);
        // 设置主题
        message.setSubject(subject.getSubject());
        // 设置邮件内容
        message.setContent(getEmailContext(contextMaps), "text/html;charset=utf-8");
        // 发送
        Transport.send(message);
    }

    public List<String> getDefaultMail() {
        return Arrays.asList(StringUtils.split(mailDefaultUser, ","));
    }

    private String getEmailContext(Map<String, String> contextMaps) {
        return velocityBean.processEmailContext(mailAlertContext, contextMaps);
    }

    /**
     * @description 发送邮件内容及附件
     * @param recipients收件人
     * @param subject邮件主题
     * @param content邮件内容
     * @param file 附件
     */
    public void sendContentAndFileEmail(List<String> recipients, EmailSubject subject, String content, File file) {
        try {
            // 创建mime类型邮件
            final MimeMessage message = new MimeMessage(session);
            // 设置发信人
            message.setFrom(new InternetAddress(authenticator.getUsername()));
            // 设置收件人们
            final int num = recipients.size();
            InternetAddress[] addresses = new InternetAddress[num];
            for (int i = 0; i < num; i++) {
                addresses[i] = new InternetAddress(recipients.get(i));
            }
            message.setRecipients(RecipientType.TO, addresses);
            // 邮件主题
            message.setSubject(subject.getSubject());
            // 向multipart对象中添加邮件的各个部分内容，包括文本内容和附件
            Multipart multipart = new MimeMultipart();
            // 添加邮件正文
            BodyPart contentPart = new MimeBodyPart();
            contentPart.setContent(content, "text/html;charset=UTF-8");
            multipart.addBodyPart(contentPart);

            // 添加附件的内容
            if (file != null) {
                BodyPart attachmentBodyPart = new MimeBodyPart();
                DataSource source = new FileDataSource(file);
                attachmentBodyPart.setDataHandler(new DataHandler(source));
                // MimeUtility.encodeWord可以避免文件名乱码
                attachmentBodyPart.setFileName(MimeUtility.encodeWord(file.getName()));
                multipart.addBodyPart(attachmentBodyPart);
            }

            // 将multipart对象放到message中
            message.setContent(multipart);
            // 发送
            Transport.send(message);
            System.out.println("send success!");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}
